<?php
/**
 * 
 * +------------------------------------------------------------+
 * @category Select 
 * +------------------------------------------------------------+
 * 根据传递不同的参数自动组装成通用性SQL查询语句
 * +------------------------------------------------------------+
 *
 * @author anzai <236049524@qq.com>
 * @copyright http://www.judianyun.com 2012
 * @version 1.0
 *
 * Modified at : 2012-02-17 11:02:46
 *
 */
class Select extends Base {
	const DISTINCT       	= 'distinct';
    const COLUMNS        	= 'columns';
    const FROM           	= 'from';
    const WHERE          	= 'where';
    const GROUP          	= 'group';
    const HAVING         	= 'having';
    const ORDER          	= 'order';
    const LIMIT_COUNT    	= 'limitcount';
    const LIMIT_OFFSET   	= 'limitoffset';
	const JOIN			 	= 'join';
    const INNER_JOIN     	= 'inner join';
    const LEFT_JOIN      	= 'left join';
    const RIGHT_JOIN     	= 'right join';
    const FULL_JOIN      	= 'full join';
    const CROSS_JOIN     	= 'cross join';
    const NATURAL_JOIN   	= 'natural join';
    const SET				= 'SET';
	
    const SQL_WILDCARD   	= '*';
    const SQL_SELECT     	= 'SELECT';
    const SQL_FROM       	= 'FROM';
    const SQL_WHERE      	= 'WHERE';
    const SQL_DISTINCT   	= 'DISTINCT';
    const SQL_GROUP_BY   	= 'GROUP BY';
    const SQL_ORDER_BY   	= 'ORDER BY';
    const SQL_HAVING     	= 'HAVING';
    const SQL_IN			= 'IN';
    const SQL_NOT_IN		= 'NOT IN';
    const SQL_BETWEEN		= 'BETWEEN';
    const SQL_LIMIT		 	= 'LIMIT';
    const SQL_LIKE			= 'LIKE';
    const SQL_AND        	= 'AND';
    const SQL_AS         	= 'AS';
    const SQL_OR         	= 'OR';
    const SQL_ON        	= 'ON';
    const SQL_ASC        	= 'ASC';
    const SQL_DESC       	= 'DESC';
    const SQL_INNER_JOIN 	= 'INNER JOIN';
    const SQL_LEFT_JOIN  	= 'LEFT JOIN';
    const SQL_RIGHT_JOIN 	= 'RIGHT JOIN';
    const SQL_FULL_JOIN  	= 'FULL JOIN';
    const SQL_CROSS_JOIN 	= 'CROSS JOIN';
    const SQL_NATURAL_JOIN 	= 'NATURAL JOIN';
    const SQL_UPDATE		= 'UPDATE';
    const SQL_INSERT		= 'INSERT INTO';
    const SQL_SET			= 'SET';
    const SQL_DELETE		= 'DELETE';
    const SQL_TRUNCATE	 	= 'TRUNCATE TABLE';
    const SQL_EMPTY			= ' ';
    
    private static $_join_func	=	array('cross', 'natural', 'full');
    
    ///Model对象
    private $_model = null;
	
    ///设置条件组合
	private $_part = array();
	
	///查询条件初始化
	protected static $_partInit = array(
		self::COLUMNS		=> array(),
		self::DISTINCT		=> false,
		self::WHERE			=> null,
		self::GROUP			=> array(),
		self::FROM			=> array(),
		self::ORDER			=> array(),
		self::HAVING		=> null,
		self::LIMIT_COUNT	=> null,
        self::LIMIT_OFFSET	=> null,
        self::JOIN			=> array(),
		self::SET			=> array()
	);
	
	///连接查询类型
	private static $_joinArray = array(
		self::INNER_JOIN	=> self::SQL_INNER_JOIN,
		self::LEFT_JOIN		=> self::SQL_LEFT_JOIN,
		self::RIGHT_JOIN	=> self::SQL_RIGHT_JOIN,
		self::FULL_JOIN		=> self::SQL_FULL_JOIN,
		self::CROSS_JOIN	=> self::SQL_CROSS_JOIN,
		self::NATURAL_JOIN	=> self::SQL_NATURAL_JOIN
	);
	
	//当前操作的数据库类型，默认为mysql
	private static $_dbType = 'mysql';
	
	private $_condstr = '';
	
	/**
	 * 
	 * +------------------------------------------------------------+
	 * @name __construct
	 * +------------------------------------------------------------+
	 * 架构函数
	 * +------------------------------------------------------------+
	 *
	 * @author anzai <236049524@qq.com>
	 * @version 1.0
	 *
	 * @example
	 *
	 * @param string $dbtype 设置所连接的数据库类型，默认为mysql
	 *
	 */
	public function __construct($dbtype=null){
		$this->_part = self::$_partInit;
		if ($dbtype !== null)
			self::$_dbType = $dbtype;
	}
	
	/**
	 * 
	 * +------------------------------------------------------------+
	 * @name column
	 * +------------------------------------------------------------+
	 * 设置需要查询的字段，可同时调用多次，每次进行累加
	 * +------------------------------------------------------------+
	 *
	 * @author anzai <236049524@qq.com>
	 * @version 1.0
	 *
	 * @example
	 * 		$Select->column('id') //增加一id字段
	 * 		$Select->column(array('id','name'))//增加id和name字段
	 * 		$Select->column(array('a'=>'id','b'=>'name'))//增加id和name字段，并将id重命名为a，name重命名为b
	 * 		$Select->column(array('a'=>array('id','name')))//其中a为表的别名
	 * 		$Select->column(array('a'=>array('c'=>'id','d'=>'name')))//a为表的别名，c和d为字段的别名
	 *
	 * @param mixed $field 其中$field可为一个字符串、一维数组或二维数组
	 * @return 返回Select对象本身
	 *
	 */
	public function column($field=null){
		if (null!==$field && $field){
			if (is_array($field)){
				foreach ($field as $key => $val){
					if (is_array($val)){
						foreach ($val as $k => $v)
							$this->_part[self::COLUMNS][] = (is_string($key) ? $key . '.' . $v : $v) . (is_string($k) ? self::SQL_EMPTY . self::SQL_AS . self::SQL_EMPTY . '`'.$k.'`' : '');
					}else
					    $this->_part[self::COLUMNS][] = is_string($key) ? $val . self::SQL_EMPTY . self::SQL_AS . self::SQL_EMPTY . '`' .$key . '`' : $val;
				}
			}else
				$this->_part[self::COLUMNS][] = $field;
		}
		return $this;
	}
	
	//column的别名
	public function field($field){
		return $this->column($field);
	}
	
	//根据条件自动组装删除数据SQL语句
	public function delete(){
		$where = $this->_parseInner(self::WHERE);
		$table = $this->_parseTable(true);
		
		//无设置删除条件，则清空表
		if ($where == ''){
			$sql = self::SQL_TRUNCATE . str_replace(self::SQL_FROM, '', $table);
		}else{
			$sql = self::SQL_DELETE . self::SQL_EMPTY . $table . $where;
		}
		
		return $sql;
	}
	
	/**
	 * 是否使查询结果值唯一
	 * @param boolean $flag true：是    flase：否
	 */
	public function distinct($flag = true){
		$this->_part[self::DISTINCT] = (bool) $flag;
		
		return $this;
	}
	
	/**
	 * 设置查询的表（可调用多次设置需要查询的表或同时设置多个表）
	 * 
	 * @param mixed $table 一个表或多个表（使用数组）
	 * @param mixed $cols 设置需要查询的字段，设置方法同方法column的参数的设置方法一致
	 * 
	 * $table的设置方法：
	 * 1、tablename
	 * 2、tablename as a 或 array('a'=>'tablename')设置表别名为a
	 * 3、array(tablename1,tablename2) 关联查询时同时设置两个表：tablename1和tablename2
	 * 4、array('a'=>tablename1,'b'=>tablename1) 关联查询时同时
	 * 设置两个表：tablename1（设置别名为a）和tablename2（设置别名b）
	 */
	public function from($table, $cols=null){
		if (is_array($table)){
			foreach ($table as $key => $val){
				$tmpTable = is_string($key) ? array($key, $val) : $val;
				if(in_array($tmpTable, $this->_part[self::FROM])) continue;
				$this->_part[self::FROM][] = $tmpTable;
				unset($tmpTable);
			}
		}else{
			$this->_part[self::FROM][] = $table;
		}
		$this->column($cols);
		
		return $this;
	}
	
	/**
	 * FULL JOIN
	 */
	public function full($joinType, $tablename, $on, $col=null){
		return $this->_join(self::FULL_JOIN, $tablename, $on, $col);
	}
	
	/**
	 * 增加GROUP BY分组查询，一次支持同时增加多个
	 * 如：$Select->group('id')或$Select->group('id','name')
	 * 
	 * @return 返回Select对象本身
	 */
	public function group(){
        $spec = func_get_args();
        if ($spec){
	        foreach ($spec as $val) {
	        	if (!is_array($val)){
	        		$val = (string) $val;
	        		if(in_array($val, $this->_part[self::GROUP])) continue;
	        		$this->_part[self::GROUP][] = $val;
	        	}else{
	        		foreach ($val as $g){
	        			$g = (string) $g;
	        			if(in_array($g, $this->_part[self::GROUP])) continue;
	        			$this->_part[self::GROUP][] = $g;
	        		}
	        	}
	        }
        }
        return $this;
	}
	
	/**
	 * 增加HAVING条件查询字句，有多个时默认按AND连接
	 * 
	 * @param string $condition 条件，有传入值用占位符“?”表示
	 * @param mixed $replace 替换值，多个用数组
	 * @param boolean $bool 一个布尔值 ：true表示AND，flase表示OR
	 * 
	 * @return 返回Select对象本身
	 */
	public function having($condition, $replace=null, $bool=true){
		if($condition){
			if (is_array($condition)){
				foreach ($condition as $field => $value){
					if (is_numeric($field)){
						$this->having($value, null, $bool);
					}else{
						$field = false === strpos($field, '?') ? $field . '=?' : $field;
						$this->having($field, $value, $bool);
					}
				}
			}else{
				$cond = $bool===true ? self::SQL_AND : self::SQL_OR;
				$condition = $replace===null ? $condition : $this->quoteInto($condition, $replace);
				$this->_part[self::HAVING] .= empty($this->_part[self::HAVING]) ? ($condition) : self::SQL_EMPTY . $cond . ' (' . $condition . ')';
			}
		}
		
		return $this;
	}
	
	/**
	 * 
	 * +------------------------------------------------------------+
	 * @name _parseIn
	 * +------------------------------------------------------------+
	 * Enter functional description here ...
	 * +------------------------------------------------------------+
	 *
	 * @example
	 * _parseIn('id','1,2,3') 或 _parseIn('id',array(1,2,3))
	 * _parseIn(array('id' => array(1,2)), array('name'=>'a,b,c'))
	 *
	 * @param mixed $field	字段，为数组表示一次性设置多个
	 * @param mixed $range  区间，若一次性设置多个，则该参数表示条件连接方式，默认null表示AND
	 * @param boolean $not  true表示NOT IN
	 * @param boolean $bool 区间设置好后进行条件连接方式， true:AND false:OR
	 *
	 */
	public function _parseIn($field, $range = null, $not = false, $bool = true){
		if (!$range && $range != 0) return $this;
		if (is_array($field)){
			$bool = $range === null || $range === true ? true : false;
			foreach ($field as $k => $f){
				$this->_parseIn($k, $f, $not, $bool);
			}
		}else if (is_string($field)){
			$field = trim($field);
			$range = is_array($range) ? $range : explode(',', trim($range));
			
			if($field != '' && !preg_match('/\s+/', $field) && count($range) > 0){
				$field = false === strpos($field, '.') ? '`' . $field . '`' : $field;
				$inRange = array();
				foreach ($range as $v){
					$inRange[] = "'$v'";
				}
				$condition = $field . self::SQL_EMPTY . ($not ? self::SQL_NOT_IN : self::SQL_IN) . self::SQL_EMPTY . '(' . implode(',', $inRange) . ')';
				$this->where($condition, null, $bool);
				unset($inRange, $condition);
			}
		}
		
		return $this;
	}
	
	/**
	 * IN查询
	 */
	public function in($field, $range = '', $bool = true){
		if ($range == '') return $this;
		return $this->_parseIn($field, $range, false, $bool);
	}
	
	/**
	 * NOT IN查询
	 */
	public function notIn($field, $range = '', $bool = true){
		if ($range == '') return $this;
		return $this->_parseIn($field, $range, true, $bool);
	}
	
	//设置内联连接查询
	public function inner($tablename, $on, $col=null){
		return $this->_join(self::INNER_JOIN, $tablename, $on, $col);
	}
	
	/**
	 * 判断某个SQL字句是否已设置并不为空，未设置或为空则返回true
	 * 
	 * @param string $part
	 */
	public function isEmpty($part){
		return !isset($this->_part[$part]) || empty($this->_part[$part]);
	}
	
	/**
	 * 方法inner的别名
	 */
	public function joins($tablename, $on, $col=null){
		return $this->inner($tablename, $on, $col);
	}
	
	/**
	 * 新增LEFT JOIN、INNER JOIN、RIGHT JOIN、FULL JOIN、CROSS JOIN、NATURAL JOIN
	 * 
	 * @param string $joinType 类型
	 * @param mixed $tablename 表名（格式如：tablename或array(表别名=>tablename)）
	 * @param string $on 连接条件，单个字段会字段加上表前缀，也可为数组，若为数组连接方式为AND
	 * @param string $col 用法同类方法column的参数一致
	 */
	private function _join($joinType, $tablename, $on, $col=null){
		if (!array_key_exists($joinType, self::$_joinArray)) return;
		
		if ($on !== true || !is_array($tablename)){
		    if (!is_array($tablename) && is_string($col) && false === strpos($col, ',')){
		        $col = $tablename . '.' . $col;
		    }
		    
		    $this->column($col);
		    
		    $this->_part[self::JOIN][] = array('table' => $tablename, 'on' => $on, 'type' => $joinType);
		}else{
		    foreach ($tablename as $vo){
		        $t = isset($vo['alias']) ? array($vo['alias'] => $vo['table']) : $vo['table'];
		        $this->_join($joinType, $t, $vo['on'], isset($vo['col']) ? $vo['col'] : '');
		    }
		}
		
		return $this;
	}
	
	/**
	 * 新增LEFT JOIN字句
	 * 
	 * @param mixed $tablename
	 * @param mixed $on
	 * @param mixed $col
	 */
	public function left($tablename, $on, $col=null){
		return $this->_join(self::LEFT_JOIN, $tablename, $on, $col);
	}
	
	/**
	 * 设置LIMIT条件语句
	 * 
	 * @param int $count 每次取出条数
	 * @param int $offset 偏移量
	 * 
	 * @return 返回Select对象本身
	 * 
	 */
	public function limit($count=null, $offset=null){
		$this->_part[self::LIMIT_COUNT] = (int) $count;
		$this->_part[self::LIMIT_OFFSET] = (int) $offset;
		
		return $this;
	}
	
	/**
	 * 数据库Like关键字查询
	 *
	 * @param string $field
	 * @param string $value
	 * @param string $bool	true：AND关联查询  false：OR关联查询
	 * @return Model
	 */
	public function like($field, $value, $bool = true){
		if (strpos($field, '|') || strpos($field, '&')){
			$field = str_replace(array('|', '&'), array(' LIKE ? OR ', ' LIKE ? AND '), $field);
		}
		$field .= ' LIKE ?';
		$c = substr_count($field, '?');
		if ($c > 1){
			$value = is_array($value) ? $value : Helper::repeat($value, $c);
		}
		return $this->where($field, $value, $bool);
	}
	
	public function notLike($field, $value, $bool = true){
		if (strpos($field, '|') || strpos($field, '&')){
			$field = str_replace(array('|', '&'), array(' NOT LIKE ? OR ', ' NOT LIKE ? AND '), $field);
		}
		$field .= ' NOT LIKE ?';
		$c = substr_count($field, '?');
		if ($c > 1){
			$value = is_array($value) ? $value : Helper::repeat($value, $c);
		}
		return $this->where($field, $value, $bool);
	}
	
	/**
	 * 增加ORDER BY查询字句，默认按ASC
	 * 
	 * @param mixed $spec 可为一个字段名称或多个，多个使用数组
	 * @param boolean $direction 一个布尔值 ：true表示ASC，flase表示DESC
	 * 
	 * @return 返回Select对象本身
	 */
	public function order($spec, $direction=true){
		if ($spec){
			$direction = $direction===true ? self::SQL_ASC : self::SQL_DESC;
			$spec = is_array($spec) ? $spec : array($spec);
			foreach ($spec as $order){
				$order = (string) $order;
				if ($order == '') continue;
				$this->_part[self::ORDER][] = $order . self::SQL_EMPTY . $direction;
			}
		}
		return $this;
	}
	
	/**
	 * 随机排序
	 */
	public function rand(){
		if (!in_array('RAND()', $this->_part[self::ORDER])){
			$this->_part[self::ORDER][] = 'RAND()';
		}
		
		return $this;
	}
	
	//设置自动升序排序
	public function asc($spec){
		return $this->order($spec, true);
	}
	
	//设置字段降序排序
	public function desc($spec){
		return $this->order($spec, false);
	}
	
	/**
	 * 按当前页码自动设置LIMIT条件语句
	 * @param int $p 当前页数
	 * @param int $count 每次显示条数
	 * 
	 * @return 返回Select对象本身
	 */
	public function page($p, $count){
		$p = $p > 0 ? $p : 1;
		$count = $count > 0 ? $count : 1;
		$this->limit($count, $count * ($p - 1));
		return $this;
	}
	
	private function _parseLimit(){
		$string = '';
		if ($this->_part[self::LIMIT_COUNT] || $this->_part[self::LIMIT_OFFSET]){
			$count = $this->_part[self::LIMIT_COUNT] > 0 ? $this->_part[self::LIMIT_COUNT] : 1;
			$offset = $this->_part[self::LIMIT_OFFSET] > 0 ? $this->_part[self::LIMIT_OFFSET] : 0;
			switch (self::$_dbType){
				case 'msssql':
					break;
				default :
					$string = self::SQL_LIMIT . self::SQL_EMPTY . $offset . ',' . $count;
			}
		}
		return $string;
	}
	
	/**
	 * 解析GROUP BY、ORDER BY、HAVING、WHERE语句
	 * @param string $part
	 * @return string 返回解析后的语句
	 */
	private function _parseInner($part){
		$string = '';
		switch ($part){
			case self::COLUMNS: //解析所有查询的字段名
				$string = (!$this->isEmpty($part) ? implode(',', $this->_part[$part]) : self::SQL_WILDCARD) . self::SQL_EMPTY;
				break;
			case self::DISTINCT:
				$string = $this->_part[$part] === true ? self::SQL_DISTINCT . self::SQL_EMPTY : '';
				break;
			case self::GROUP ://解析GROUP BY语句
				if (!$this->isEmpty($part))
					$string = self::SQL_GROUP_BY . self::SQL_EMPTY . implode(',', $this->_part[$part]) . self::SQL_EMPTY;	
				break;
			case self::HAVING ://解析HAVING语句
				$string = empty($this->_part[$part]) ? '' : self::SQL_HAVING . self::SQL_EMPTY . $this->_part[$part] . self::SQL_EMPTY;
				break;
			case self::ORDER ://解析ORDER BY语句
				if (!$this->isEmpty($part))
					$string = self::SQL_ORDER_BY . self::SQL_EMPTY . implode(',', $this->_part[$part]) . self::SQL_EMPTY;
				break;
			case self::WHERE ://解析WHERE语句
				$string = empty($this->_part[$part]) ? '' : self::SQL_WHERE . self::SQL_EMPTY . $this->_part[$part] . self::SQL_EMPTY;
				break;
			default:
		}
		return $string;
	}
	
	/**
	 * 解析连接查询SQL语句
	 */
	private function _parseJoin(){
		if ($this->_part[self::JOIN]){
			$join = '';
			foreach ($this->_part[self::JOIN] as $j){
				$join .= self::$_joinArray[$j['type']] . self::SQL_EMPTY;
				if (is_array($j['table'])){
					$keys =  array_keys($j['table']);
					$join .= $j['table'][$keys[0]] . self::SQL_EMPTY . self::SQL_AS . self::SQL_EMPTY. $keys[0];
					unset($keys);
				}else{
					$join .= $j['table'];
				}
				$join .= $this->_parseOn($j['on']);
			}
		}
		return $join;
	}
	
	/**
	 * 解析连接ON条件
	 */
	private function _parseOn($on){
		$on_str = '';
		if (is_array($on)){
			$tmpOn = array();
			foreach ($on as $k => $v){
				if (is_numeric($k)){
					$tmpOn[] = '(' . $v . ')';
				}else if (is_string($k)){
					$k = trim($k);
					$string = !preg_match('/\s+/', $k) ? $k . '=?' : $k;
					$tmpOn[] = '(' . $this->quoteInto($string, $v) . ')';
					unset($string);
				}
			}
			$on_str = '(' . implode(' AND ', $tmpOn).')';
			unset($tmpOn);
		}else{
			$on_str = $on;
		}
		
		return empty($on_str) ? '' : self::SQL_EMPTY . self::SQL_ON . self::SQL_EMPTY . $on_str . self::SQL_EMPTY;
	}
	
	private function _parseTable($one=false, $join_from = true){
		try {
			if ($this->isEmpty(self::FROM))
				throw new E(Helper::L('CLS_SELECT_TABLE'), EXCEPTION_T_DB);
			switch (self::$_dbType){
				case 'msssql':
					break;
				
				default :
					if ($one) krsort($this->_part[self::FROM]);
					foreach ($this->_part[self::FROM] as $t){
						if ($one){
							$table[] = is_array($t) ? $t[0] : $t;
							break;
						}else{
							$table[] = is_array($t) ? $t[1] . self::SQL_EMPTY . self::SQL_AS . self::SQL_EMPTY . $t[0] : $t;
						}
					}
					
					$table = implode(',', $table);
			}
		}catch (E $e){
			$e->getMsg();
		}
		
		return ($join_from ? self::SQL_FROM : '') . self::SQL_EMPTY . $table . self::SQL_EMPTY;
	}
	
	/**
	 * 新增RIGHT JOIN字句
	 * @param mixed $tablename
	 * @param mixed $on
	 * @param mixed $col
	 */
	public function right($tablename, $on, $col=null){
		return $this->_join(self::RIGHT_JOIN, $tablename, $on, $col);
	}
	
	public function setModel($model){
		$this->_model = $model;
	}
	
	/**
	 * 根据所有条件组装成一条完整的SELECT SQL语句
	 */
	public function sql(){
		$sql = self::SQL_SELECT . self::SQL_EMPTY;
		$sql .= $this->_parseInner(self::DISTINCT); 
		$sql .= $this->_parseInner(self::COLUMNS);
		$sql .= $this->_parseTable();
		$sql .= $this->_parseJoin();
		$sql .= $this->_parseInner(self::WHERE);
		$sql .= $this->_parseInner(self::GROUP);
		$sql .= $this->_parseInner(self::HAVING);
		$sql .= $this->_parseInner(self::ORDER);
		$sql .= $this->_parseLimit();
		return $sql;
	}
	
	
	/**
	 * 重置已经设置的条件
	 * @param string $part 指定要重置的部分，默认为null表示重置所有的设置
	 * 
	 * @return 返回Select对象本身
	 */
	public function reset($part=null){
		if ($part===null){
			$this->_part = self::$_partInit;
		}elseif (array_key_exists($part, self::$_partInit)){
			$this->_part[$part] = self::$_partInit[$part];
		}
		
		return $this;
	}
	
	/**
	 * 新增WHERE查询的AND或OR条件语句
	 * 
	 * @param mixed  $condition 条件，有传入值用占位符“?”表示
	 * @param mixed  $replace 替换值，多个用数组，若为布尔值且$condition为数组则表示进行条件分组（true表示AND，flase表示OR）
	 * @param boolean $bool 一个布尔值 ：true表示AND，flase表示OR；若$replace为布尔值，则该值表示分组后进行连接方式
	 * 如：
	 * $Select->where("id=$id") 或   $Select->where('id=?',$id) 或
	 * $Select->where(array('id'=>$id,...))
	 * LIKE的用法：
	 * 		$condition['_LIKE_'] = array(
	 * 			'col' => '%value%', 
	 * 			'col1|col2' => '%value%', // 解析成 col1 like '%value%' OR col2 like '%value%'
	 * 			'col3&col4|col5' => '%value%' //解析成 col3 like '%value%' AND col4 like '%value%' OR col5 like '%value%'
	 * 		)
	 * 
	 * @return 返回Select对象本身
	 */
	public function where($condition, $replace=null, $bool=true){
		$condition = is_string($condition) ? trim($condition) : $condition;
		if ($condition){
			if(is_array($condition)){
				$condstr = '';
				if (is_bool($replace)){
					$cond = $bool === true ? self::SQL_AND : self::SQL_OR;
					$bool = $replace;
					$condstr = empty($this->_part[self::WHERE]) ? '' : self::SQL_EMPTY . $cond . self::SQL_EMPTY;
					unset($cond);
				}
				foreach ($condition as $field => $value){
					if ($field === '_IN_' && is_array($value)){
						foreach ($value as $in_col => $in_value){
							$in_value = isset($in_value['value']) ? $in_value : array('value' => $in_value, 'bool' => true);
							$this->in($in_col, $in_value['value'], $in_value['bool']);
						}
					}elseif ($field === '_NOT_IN_' && is_array($value)){
						foreach ($value as $in_col => $in_value){
							$in_value = isset($in_value['value']) ? $in_value : array('value' => $in_value, 'bool' => true);
							$this->notIn($in_col, $in_value['value'], $in_value['bool']);
						}
					}elseif ($field === '_LIKE_' && is_array($value)){
						foreach ($value as $like_col => $like_value){
							$like_value = isset($like_value['value']) ? $like_value : array('value' => $like_value, 'bool' => true);
							$this->like($like_col, $like_value['value'], $like_value['bool']);
						}
					}elseif ($field === '_NOT_LIKE_' && is_array($value)){
						foreach ($value as $like_col => $like_value){
							$like_value = isset($like_value['value']) ? $like_value : array('value' => $like_value, 'bool' => true);
							$this->notLike($like_col, $like_value['value'], $like_value['bool']);
						}
					}elseif (is_numeric($field)){
						$this->where($value, null, $bool);
					}else{
						$field = false === strpos($field, '?') ? $field . '=?' : $field;
						$this->where($field, $value, $bool);
					}
				}
				is_bool($replace) && $this->_part[self::WHERE] = $condstr . '(' . $this->_part[self::WHERE] . ')';
				unset($condstr);
			}else{
				$cond = $bool === true ? self::SQL_AND : self::SQL_OR;
				
				//指定字段进行OR或AND分组连接
				if (is_string($condition) && false == strpos($condition, '?') && is_array($replace) && count($replace) > 0 && !preg_match('/\s+/', $condition)){
					$condstr = empty($this->_part[self::WHERE]) ? '' : self::SQL_EMPTY . $cond . self::SQL_EMPTY;
					$condition = $condition . '=?';
					if (is_array($replace[0])){
						$b = !isset($replace[1]) || $replace[1] === true ? true : false;
						$values = $replace[0];
					}else{
						$b = true;
						$values = $replace;
					}
					
					foreach ($values as $r){
						$this->where($condition, $r, $b);
					}
					$this->_part[self::WHERE] = $condstr . '(' . $this->_part[self::WHERE] . ')';
					unset($b, $condstr, $values);
				}else{
					$condition = '(' . ($replace === null ? $condition : $this->quoteInto($condition, $replace)) . ')';
					$this->_part[self::WHERE] .= empty($this->_part[self::WHERE]) ? $condition : self::SQL_EMPTY . $cond . self::SQL_EMPTY . $condition;
				}
			}
		}
		unset($condition, $replace, $bool);
		return $this;
	}
	
	//设置AND条件语句
	public function andWhere($condition, $replace=null){
		$this->where($condition, $replace, true);
		
		return $this;
	}
	
	//设置OR条件语句
	public function orWhere($condition, $replace=null){
		if (is_string($condition) && false == strpos($condition, '?') && is_array($replace) && count($replace) > 0 && !preg_match('/\s+/', $condition)){
			$replace = array($replace, false);
		}
		$this->where($condition, $replace, false);
		
		return $this;
	}
	
	//过滤数据，防SQL注入
	private function _escape($value){
		//若是数组则进行序列化
		if (is_array($value)) return serialize($value);
		
		defined('MAGIC_QUOTES_GPC') or define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc());
		if (!MAGIC_QUOTES_GPC){
			switch (self::$_dbType){
				case 'mysql':
			        $value = addslashes($value);
					break;
				default :
					$value = addslashes($value);
			}
		}
		return str_replace("?", "&qnmark;", $value);
	}
	
	//对数据加入“`”符号处理
	public function addQuoMark($arr){
		if ($arr == '' || is_string($arr)) return $arr;
		$sep = '`';
		$regex = '/^[a-zA-Z_]+(\w)*$/';
		$empty = md5('__IS__NULL__');
		
		$tmpstr = array();
		
		foreach ($arr as $key => $val){
			$isstr = preg_match($regex, $key);
			if ($val === $empty){
				$tmpstr[] = $isstr ? $sep . $key . $sep : $sep;
			}elseif ($isstr && is_string($val) && preg_match('/^[\+\-\*]=.+$/', $val)){
				$key = $sep . $key . $sep;
				$tmpstr[] = $key . '=' . $key . substr($val, 0, 1) . substr($val, 2);
			}else{
				$tmpstr[] = $isstr ? $this->quoteInto($sep . $key . $sep . '=?', $val) : $sep . $val . $sep;
			}
		}
		
		return implode(',', $tmpstr);
	}
	
	/**
	 * quoteInto 替换占位符“?”
	 *
	 * @param string $string 被替换的字符串
	 * @param string $replace 所替换的字符串
	 * @return string 返回替换后的字符串
	 */
	public function quoteInto($string, $replace=''){
		if (false===strpos($string,'?') || $string == '')
			return $string;
			
		$replace = is_array($replace) ? $replace : array($replace);
		$pos = strpos($string,'?');
		$i = 0;
		while (false!==$pos){
			$string = ($pos && '/' == substr($string, $pos-1,1)) ? substr_replace($string, $this->_escape($replace[$i++]), $pos-1, 2) : substr_replace($string, "'" . $this->_escape($replace[$i++]) . "'", $pos, 1);
			$pos = strpos($string, '?', $pos);
		}
		unset($replace);
		return str_replace("&qnmark;", "?", $string);
	}
	
	/**
	 * 根据条件自动组装Update SQL语句
	 * @return string
	 */
	public function update(){
		$set = $this->_parseSet();
		if ($set != ''){
			$where = $this->_parseInner(self::WHERE);
			$table = $this->_parseTable(true, false);
			$sql = self::SQL_UPDATE . $table . self::SQL_EMPTY . self::SQL_SET . $set . $where;
			return $sql;
		}
	}
	
	private function _parseSet(){
		if (count($this->_part[self::SET]) > 0){
			$set = $this->getSelect()->addQuoMark($this->_part[self::SET]);
			
			return self::SQL_EMPTY . $set . self::SQL_EMPTY;
		}
	}
	
	/**
	 * 设置要插入或更新字段值
	 * @param mixed $field	字符串或数组
	 * @param string $value
	 */
	public function setvalue($field, $value = ''){
		if (is_array($field)){
			$this->_part[self::SET] = extend($this->_part[self::SET], $field);
		}else{
			$this->_part[self::SET][$field] = $value;
		}
	}
	
	/**
	 * 将Select对象转换为一条SQL语句
	 */
	public function __toString(){
		return $this->sql();
	}
	
	//调用Select方法不存在时则默认调用Model中的方法
	public function __call($name,$args){
		if (in_array(strtolower($name), self::$_join_func)){
			return $this->$name($args[0], $args[1], $args[2]);
		}else if (method_exists($this->_model, $name)){
			return $this->_model->$name();
		}
		
		return $this;
	}
	
	public function __destruct(){
		$this->_model = null;
	}
}

?>